package top.mcwebsite.markdown.render

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import org.intellij.markdown.IElementType
import org.intellij.markdown.MarkdownElementTypes
import org.intellij.markdown.ast.ASTNode
import org.intellij.markdown.ast.findChildOfType
import org.intellij.markdown.ast.getTextInNode
import org.intellij.markdown.flavours.gfm.GFMTokenTypes
import top.mcwebsite.markdown.MarkdownState
import top.mcwebsite.markdown.model.MarkdownNode
import top.mcwebsite.markdown.theme.LocalMarkdownTheme

object UnOrderedListComponent : MarkdownListComponent {

    @Composable
    override fun render(markdownNode: MarkdownNode, level: Int) {
        val theme = LocalMarkdownTheme.current
        Column(
            modifier = Modifier.padding(theme.blockPadding)
        ) {
            markdownNode.node.children
                .filter { it.type == MarkdownElementTypes.LIST_ITEM }
                .forEach {
                    UnOrderedListItems(
                        node = it,
                        content = markdownNode.content,
                        state = markdownNode.state,
                        renders = markdownNode.renders,
                        level = level,
                    )
                }
        }
    }

    @Composable
    fun UnOrderedListItems(
        node: ASTNode,
        content: String,
        state: MarkdownState,
        renders: Map<IElementType, MarkdownComponent>,
        level: Int,
    ) {
        val theme = LocalMarkdownTheme.current
        Column(
            modifier = Modifier.padding(theme.unOrderedListTheme.itemPadding)
        ) {
            if (node.findChildOfType(GFMTokenTypes.CHECK_BOX) != null) {
                CheckBox(astNode = node, content = content, markdownState = state)
            } else {
                UnOrderedListItem(
                    node = node,
                    content = content,
                    state = state,
                )
            }
            node.findChildOfType(MarkdownElementTypes.UNORDERED_LIST)?.let {
                Row {
                    Spacer(Modifier.width(theme.unOrderedListTheme.nextLevelSpace))
                    render(MarkdownNode(it, content, state, renders), level + 1)
                }
            }
            node.findChildOfType(MarkdownElementTypes.ORDERED_LIST)?.let {
                Row {
                    Spacer(Modifier.width(theme.unOrderedListTheme.nextLevelSpace))
                    (renders[MarkdownElementTypes.ORDERED_LIST] as? MarkdownListComponent)
                        ?.render(MarkdownNode(it, content, state, renders), level + 1)
                }
            }
        }
    }

    @Composable
    fun UnOrderedListItem(
        node: ASTNode,
        content: String,
        state: MarkdownState,
    ) {
        val theme = LocalMarkdownTheme.current
        val unOrderedListTheme = theme.unOrderedListTheme
        Row(
            verticalAlignment = Alignment.CenterVertically
        ) {
            Box(
                modifier = Modifier
                    .padding(unOrderedListTheme.itemIndicator.padding)
                    .size(unOrderedListTheme.itemIndicator.size)
                    .background(color = unOrderedListTheme.itemIndicator.color, shape = unOrderedListTheme.itemIndicator.shape)
            )
            node.findChildOfType(MarkdownElementTypes.PARAGRAPH)?.let {
                MarkdownText(
                    content = content,
                    astNode = it,
                    markdownState = state,
                    textStyle = theme.text,
                )
            }
        }
    }

    @Composable
    fun CheckBox(astNode: ASTNode, content: String, markdownState: MarkdownState) {
        val theme = LocalMarkdownTheme.current
        val isCheckedContent = astNode.findChildOfType(GFMTokenTypes.CHECK_BOX)?.getTextInNode(content) ?: return
        val isChecked = isCheckedContent != "[ ] "
        Row(
            verticalAlignment = Alignment.CenterVertically
        ) {
            theme.unOrderedListTheme.checkBox.CheckBoxIcon(isChecked)
            astNode.findChildOfType(MarkdownElementTypes.PARAGRAPH)?.let {
                MarkdownText(
                    content = content,
                    astNode = it,
                    markdownState = markdownState,
                    textStyle = theme.text,
                )
            }
        }
    }
}